﻿using DNFImagePacks2Manager.Helpers;
using System;
using System.Buffers;
using System.Diagnostics;
using Windows.Graphics.Imaging;

namespace DNFImagePacks2Manager.NPK
{
    public class DDSMipmap
    {
        public int Width { set; get; }
        public int Height { set; get; }
        public byte[] Data { set; get; } = [];

        public SoftwareBitmap? GetPreviewImage()
        {
            return ImageHelper.ConvertBitmapToSoftwareBitmap(Data, Width, Height);
        }

        public byte[] GetDataBytes(ImageDDSFile ddsFile, out int finalWidth, out int finalHeight)
        {
            finalWidth = 0;
            finalHeight = 0;
            byte[] finalData = [];

            if (Data.Length == 0 || Width <= 0 || Height <= 0 || ddsFile == null)
                return finalData;

            int cutLeft = Math.Clamp(ddsFile.CutLeft, 0, Width - 1);
            int cutTop = Math.Clamp(ddsFile.CutTop, 0, Height - 1);
            int cutRight = Math.Clamp(ddsFile.CutRight, cutLeft + 1, Width);
            int cutBottom = Math.Clamp(ddsFile.CutBottom, cutTop + 1, Height);

            int cutWidth = cutRight - cutLeft;
            int cutHeight = cutBottom - cutTop;
            if (cutWidth <= 0 || cutHeight <= 0)
                return finalData;

            byte[] cutData = new byte[cutWidth * cutHeight * 4];
            int srcStride = Width * 4;
            int dstStride = cutWidth * 4;

            for (int y = 0; y < cutHeight; y++)
            {
                int srcRowStart = (cutTop + y) * srcStride + cutLeft * 4;
                int dstRowStart = y * dstStride;
                Array.Copy(Data, srcRowStart, cutData, dstRowStart, dstStride);
            }

            finalData = cutData;
            finalWidth = cutWidth;
            finalHeight = cutHeight;

            if (cutHeight != ddsFile.ImageHeight && cutWidth != ddsFile.ImageWidth)
            {
                finalWidth = cutHeight;
                finalHeight = cutWidth;
                finalData = RotateCounterClockwise90(cutData, cutWidth, cutHeight);
            }
            return finalData;
        }

        public SoftwareBitmap? GetPreviewImage(ImageDDSFile ddsFile)
        {
            if (Data.Length == 0 || Width <= 0 || Height <= 0 || ddsFile == null)
                return null;

            byte[] finalData = GetDataBytes(ddsFile, out int finalWidth, out int finalHeight);
            if (finalData.Length == 0)
            {
                return null;
            }

            return ImageHelper.ConvertBitmapToSoftwareBitmap(finalData, finalWidth, finalHeight);
        }

        private byte[] RotateCounterClockwise90(byte[] srcData, int srcWidth, int srcHeight)
        {
            const int pixelSize = 4;
            int newWidth = srcHeight;
            int newHeight = srcWidth;
            byte[] dstData = ArrayPool<byte>.Shared.Rent(newWidth * newHeight * pixelSize);

            ReadOnlySpan<byte> srcSpan = srcData.AsSpan();
            Span<byte> dstSpan = dstData.AsSpan(0, newWidth * newHeight * pixelSize);

            for (int y = 0; y < srcHeight; y++)
            {
                for (int x = 0; x < srcWidth; x++)
                {
                    int srcIndex = (y * srcWidth + x) * pixelSize;
                    int dstX = y;
                    int dstY = srcWidth - 1 - x;
                    int dstIndex = (dstY * newWidth + dstX) * pixelSize;

                    srcSpan.Slice(srcIndex, pixelSize).CopyTo(dstSpan.Slice(dstIndex, pixelSize));
                }
            }

            return dstData;
        }
    }

}
